﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common;
using System.Text.RegularExpressions;
using System.Net;

namespace Site_Extractor
{
    public class TalkBackExtractor
    {

        public static List<Talkback> ExtractTalkBacks(string siteName, RuleSet RuleSet, Uri Uri, string ArticleHTML, DateTime ArticleDate, DateTime FromDate)
        {
            List<Talkback> Talkbacks = new List<Talkback>();
            if (RuleSet.TalkbackRule == null)
                return Talkbacks;

            Dal.DatabaseAbstractionLayer dal = new Dal.DatabaseAbstractionLayer();
            if (RuleSet.TalkbackRule.TalkbackEncoding == null)
                RuleSet.TalkbackRule.TalkbackEncoding = RuleSet.Encoding;
         
            try
            {
                TalkbackRule tbr = RuleSet.TalkbackRule;
                //If Needs this url's host.
                string ArticleIDExtractExpression = tbr.ArticleIDExtractExpression.Replace(
                   TalkbackRule.CURRENT_HOST_TOKEN, Uri.Host);
                //Get Article ID + ContentTypeID of article if necessary.
                string articleIDExtractExpression = string.Empty;
                if (tbr.UrlContainsArticleID)
                {
                    articleIDExtractExpression = ArticleHTML;
                }
                else
                {
                    articleIDExtractExpression = Uri.ToString();
                }
                string[] acid = GetArticleIdContentId(articleIDExtractExpression,
                        ArticleIDExtractExpression, TalkbackRule.ArticleIDToken,
                        TalkbackRule.ContentTypeID1Token, TalkbackRule.ContentTypeID2Token);
                string ArticleID = acid[2];
                string ContentTypeID1 = acid[1];
                string ContentTypeID2 = acid[0];
                //New rule system
                string TalkbackGenericUrl = tbr.TalkbackGenericUrl;
                TalkbackGenericUrl = TalkbackGenericUrl.Replace(
                    TalkbackRule.ArticleIDToken, ArticleID);
                TalkbackGenericUrl = TalkbackGenericUrl.Replace(
                    TalkbackRule.ContentTypeID1Token, ContentTypeID1);
                TalkbackGenericUrl = TalkbackGenericUrl.Replace(
                    TalkbackRule.ContentTypeID2Token, ContentTypeID2);
                TalkbackGenericUrl = TalkbackGenericUrl.Replace(
                   TalkbackRule.CURRENT_HOST_TOKEN, Uri.Host);
                string page = string.Empty;

                if (tbr.ArticleContainsTalkbacks && !tbr.UrlContainsArticleID)
                    page = ArticleHTML;
                else
                    page = HttpHelper.HttpDownloader.DownloadPage(new Uri(TalkbackGenericUrl), tbr.TalkbackEncoding);

                if (page == string.Empty) // No page downloaded, no talkbacks.
                    return Talkbacks;
                //Get as much talkback data from page as possible, 
                List<Talkback> tbs = GetTalkbacksFromPage(siteName, RuleSet, ArticleDate, 
                       tbr, page, FromDate);
                //If talkback's text is located elsewhere, go get it.
                foreach (Talkback tb in tbs)
                {
                    if (tbr.UrlContainsOneTalkbackContent != null)
                    {
                        //Add Content Extraction Jobs.
                       
                            UrlContainsOneTalkbackContent tbContent =
                                tbr.UrlContainsOneTalkbackContent;
                            string ContentURL = tbContent.GenericContentUrl.Replace(
                               TalkbackRule.TalkbackIDToken, tb.ID.ToString());
                            ContentURL = ContentURL.Replace(
                                TalkbackRule.ArticleIDToken, ArticleID);
                            ContentURL = ContentURL.Replace(
                                TalkbackRule.ContentTypeID1Token, ContentTypeID1);
                            ContentURL = ContentURL.Replace(
                                TalkbackRule.ContentTypeID2Token, ContentTypeID2);
                            ContentURL = ContentURL.Replace(
                               TalkbackRule.CURRENT_HOST_TOKEN, Uri.Host);
                            tb.ContentUri = new Uri(ContentURL);
                            //tb.Text = GetTalkbackContentFromUrl(Site, new Uri(ContentURL),
                              //  tbContent.TextExtractExpression, TalkbackRule.ContentToken);
                        
                    }
                    if (DateTime.MinValue == tb.DateTime)
                        tb.DateTime = ArticleDate;
                    tb.SiteName = siteName;
                    Talkbacks.Add(tb);
                }
            }

            catch (Exception e) 
            {
                Console.WriteLine("Exception: {0}", e.Message);
                return Talkbacks; 
            }
            return Talkbacks;
           

        }

        public static string GetTalkbackContentFromUrl(RuleSet ruleSet, Uri Uri, string TextExtractExpression, string TextToken)
        {
            return GetTalkbackContentFromUrl(ruleSet, Uri, TextExtractExpression, TextToken, new WebClient());
        }

        public static string GetTalkbackContentFromUrl(RuleSet ruleSet, Uri Uri, string TextExtractExpression , string TextToken, WebClient webClient)
        {
            string page;
            string content = string.Empty;
            try
            {
                page = HttpHelper.HttpDownloader.DownloadPage(Uri, ruleSet.Encoding);
            }
            catch ( 
                System.Net.WebException e)
            {
                Console.WriteLine("Exception: {0}", e.Message);
                return content; 
            }
            TextExtractExpression = TextExtractExpression.Replace(TalkbackRule.ContentToken, @"(?<Text>.*?)");
            Regex TextRegEx = new Regex(TextExtractExpression, RegexOptions.Singleline);
            Match TextMatch = TextRegEx.Match(page);
            if (TextMatch.Success)
            {
                content = TextMatch.Groups["Text"].Value;
            }
            return HtmlStripper.StripFromHtml(content);
        }

        public static DateTime  GetGlobesDate(long globesDate) //Number of minutes since jan 1 2000
        {
           
            DateTime janfirst = new DateTime(2000,1,1);
            return janfirst.AddMilliseconds((globesDate)* 60 * 1000);
            
        }

        public static int GetTalkbackNumberFromParent(List<Talkback> talkbacks, long parentID)
        {
            foreach (Talkback tb in talkbacks)
                if (tb.ID == parentID)
                    return tb.Number;
            return 0;
        }

        public static string GetRegularExpressionString(string matchingRule)
        {
             string ReUrl = string.Empty;
             ReUrl += "(" + Regex.Escape(matchingRule) + ")";
                //ReUrl = ReUrl.Substring(0, ReUrl.Length - 1); //remove last "|"

                ReUrl = ReUrl.Replace(TalkbackRule.TitleToken, @"(?<TITLE>.*?)");
                ReUrl = ReUrl.Replace(TalkbackRule.ContentToken, @"(?<TEXT>.*?)");
                ReUrl = ReUrl.Replace(TalkbackRule.AuthorToken, @"(?<AUTHOR>.*?)");
                ReUrl = ReUrl.Replace(TalkbackRule.TalkbackIDToken, @"(?<ID>\w*)");
                ReUrl = ReUrl.Replace(TalkbackRule.TalkbackNumberToken, @"(?<NUMBER>\d*)");
                ReUrl = ReUrl.Replace(TalkbackRule.PARENTNUMBERTOKEN, @"(?<PARENT>\d*)");
                ReUrl = ReUrl.Replace(TalkbackRule.DateTimeToken, @"(?<DATETIME>.*?)");
                ReUrl = ReUrl.Replace(TalkbackRule.DateToken, @"(?<DATE>.*?)");
                ReUrl = ReUrl.Replace(TalkbackRule.TimeToken, @"(?<TIME>.*?)");
                ReUrl = ReUrl.Replace(TalkbackRule.GlobesDateToken, @"(?<GLOBESDATE>(\d)+)");
                ReUrl = ReUrl.Replace(TalkbackRule.WILDCARDTOKEN, @"(.*?)");
                ReUrl = ReUrl.Replace(TalkbackRule.NUMBERTOKEN, @"(\d+)");
                ReUrl = ReUrl.Replace(TalkbackRule.TEXTTOKEN, @"(\w+)");
                return ReUrl;
        }

        public static List<Talkback> GetTalkbacksFromPage(string siteName, RuleSet RuleSet, DateTime ContentDate, TalkbackRule Tbr, string ArticleHTML, DateTime FromDate)
        {
            List<Talkback> TalkbackIDs = new List<Talkback>();
            string page = ArticleHTML;
            //Strip newlines and tabs.
            if (Tbr.StripNewlinesAndTabs)
            {
                page = page.Replace("\t", "");
                page = page.Replace("\n", "");
                page = page.Replace("\r", "");
            }
            foreach (string m in Tbr.MatchingRules)
            {

                Regex UrlRegEx = new Regex(GetRegularExpressionString(m), RegexOptions.Singleline | RegexOptions.Compiled);
                Match UrlMatch = UrlRegEx.Match(page);
                int tbNum = 0;
                while (UrlMatch.Success)
                {
                    tbNum++;
                    string date = string.Empty, time = string.Empty;
                    try
                    {
                        Talkback TB = new Talkback();

                        TB.SiteName = siteName;

                        if (UrlMatch.Groups["TITLE"].Success)
                            TB.Title = HtmlAgilityPack.HtmlStripper.GetText(UrlMatch.Groups["TITLE"].Value);
                        if (UrlMatch.Groups["TEXT"].Success)
                            TB.Text = HtmlAgilityPack.HtmlStripper.GetText(UrlMatch.Groups["TEXT"].Value);
                        if (UrlMatch.Groups["ID"].Success)
                        if (!long.TryParse(UrlMatch.Groups["ID"].Value, out TB.ID))
                        {
                            TB.ID = tbNum;
                        }
                        if (UrlMatch.Groups["NUMBER"].Success)
                            TB.Number = Int32.Parse(UrlMatch.Groups["NUMBER"].Value);
                        //If couldn't find TB number, find from parent.
                        if (TB.Number == 0) 
                        {
                            if (UrlMatch.Groups["PARENT"].Success)
                                TB.Number = GetTalkbackNumberFromParent(TalkbackIDs, 
                                    long.Parse(UrlMatch.Groups["PARENT"].Value));
                            //no parent TB number, give default.
                            if (TB.Number == 0)
                                TB.Number = tbNum;
                            
                        }
                        if (UrlMatch.Groups["GLOBESDATE"].Success)
                            TB.DateTime = GetGlobesDate(long.Parse(UrlMatch.Groups["GLOBESDATE"].Value));
                        else
                        {
                            if (UrlMatch.Groups["DATETIME"].Success)
                            {
                                date = UrlMatch.Groups["DATETIME"].Value;
                                if (date == string.Empty)
                                    TB.DateTime = ContentDate;
                                else
                                    TB.DateTime = SiteExtractor.GetDateTimeFromString(date); 
                            }
                            else
                            {
                                if (UrlMatch.Groups["DATE"].Success)
                                    date = UrlMatch.Groups["DATE"].Value;
                                if (UrlMatch.Groups["TIME"].Success)
                                    time = UrlMatch.Groups["TIME"].Value;
                                if (time == string.Empty)
                                {
                                    if (ContentDate.TimeOfDay <= DateTime.Now.TimeOfDay)
                                        time = ContentDate.TimeOfDay.ToString();
                                    else
                                        time = DateTime.Now.TimeOfDay.ToString();
                                }
                                if (date == string.Empty)
                                    date = ContentDate.Date.ToString();
                                TB.DateTime = SiteExtractor.GetDateTimeFromString(date + " " + time);
                            }
                        }
                       
                        if (TB.DateTime >= FromDate)
                            TalkbackIDs.Add(TB);
                    }
                    catch (Exception e)
                    {
                        
                    
                        Console.WriteLine("Exception: {0}", e.Message);
                     
                    }

                    UrlMatch = UrlMatch.NextMatch();
                    
                }
            }
            return TalkbackIDs;

        }

        public static Talkback ExtractSingleTalkback(Site site, Uri Uri, RuleSet HtmlParsingRuleSet )
        {
            Talkback talkback = new Talkback();
            string page;
            try
            {
                page = HttpHelper.HttpDownloader.DownloadPage(Uri, site[RuleSet.Story].TalkbackRule.TalkbackEncoding);
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception: {0}", e.Message);
                return talkback; 
            }
            var nodes = HtmlDownloader.GetNodes(page);
            talkback.Title = SiteExtractor.GetTextByRule(nodes, HtmlParsingRuleSet[Rule.Title]);
            //story.Summary = SiteExtractor.GetTextByRule(nodes, site[RuleSet.Story][Site.Summary]);
            talkback.Text = SiteExtractor.GetTextByRule(nodes, HtmlParsingRuleSet[Rule.Story]);
            //string sRawDateTime = SiteExtractor.GetTextByRule(nodes, HtmlParsingRuleSet[Rule.Datetime]);
            //talkback.DateTime = SiteExtractor.GetDateTimeFromString(sRawDateTime);
            return talkback;
        }

        private static string[] GetArticleIdContentId(string IDString, string IDExpression,
            string ArticleIDToken, string ContentTypeID1Token, string ContentTypeID2Token)
        {
            string[] res = new string[3];
            string ReUrl = GetRegularExpressionString(IDExpression);
            ReUrl = ReUrl.Replace(ArticleIDToken, @"(?<ARTICLEID>\w*)");
            ReUrl = ReUrl.Replace(ContentTypeID1Token, @"(?<CONTENTTYPEID1>\w*)");
            ReUrl = ReUrl.Replace(ContentTypeID2Token, @"(?<CONTENTTYPEID2>\w*)");
         
            Regex UrlRegEx = new Regex(ReUrl,RegexOptions.IgnoreCase|RegexOptions.Compiled);
            Match UrlMatch = UrlRegEx.Match(IDString);
            if (!UrlMatch.Success)
                return res;
           
                res[0] = UrlMatch.Groups["CONTENTTYPEID2"].Value;
                res[1] = UrlMatch.Groups["CONTENTTYPEID1"].Value;
                res[2] = UrlMatch.Groups["ARTICLEID"].Value;
            return res;
        }

     
    }

   

}
